/**
 * Copyright 2011 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package com.google.solarchallenge.client.gwtui.mvpinterfaces;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.google.gwt.http.client.URL;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.solarchallenge.client.gwtui.widgets.solarchallengeheaderbar.SolarChallengeHeaderBarDisplay;
import com.google.solarchallenge.shared.ValidParams;

/**
 * Parent class for all the presenterse. All Presenter classes should extend
 * this.
 *
 * This provides two important features : 1. HeaderPanel for all the Screens. 2.
 * Utility to handle HistoryTokens.
 *
 * @author Arjun Satyapal
 */
public abstract class Presenter {
  protected final String historyToken;
  protected final Map<String, List<String>> parametersMap;
  protected SolarChallengeHeaderBarDisplay solarChallengeHeaderPanelDisplay;

  protected Presenter(
      SolarChallengeHeaderBarDisplay solarChallengeHeaderPanelDisplay,
      String historyToken) {
    this.solarChallengeHeaderPanelDisplay = solarChallengeHeaderPanelDisplay;
    this.solarChallengeHeaderPanelDisplay.bind();
    this.historyToken = historyToken;
    this.parametersMap = buildListParamMap(getParameters(this.historyToken));
  }

  private String getParameters(String token) {
    if (token != null && token.contains("?")) {
      String[] params = token.split("\\?");
      return params[1];
    }
    return null;
  }

  private Map<String, List<String>> getParametersMap() {
    return parametersMap;
  }

  public String getEncodedRedirectHash() {
    List<String> tempList = getParametersMap().get(
        ValidParams.CLIENT_CALLBACK_TOKEN.getParamKey());

    if (tempList != null && tempList.size() != 0) {
      return URL.encode(tempList.get(0));
    }

    return null;
  }

  public String getParameterValue(String key) {
    List<String> list = getParametersMap().get(
        ValidParams.APPLICATION_ID.getParamKey());
    if (list == null || list.size() == 0) {
      return null;
    }
    if (list.size() != 1) {
      Window.alert("Invalid URL.");
      throw new IllegalStateException("Invalid URL : " + historyToken);
    }

    return list.get(0);
  }

  /**
   * Borrowed from Window.location for GWT.
   */
  private Map<String, List<String>> buildListParamMap(String queryString) {
    Map<String, List<String>> out = new HashMap<String, List<String>>();

    if (queryString != null && queryString.length() > 1) {
      String qs = queryString;

      for (String kvPair : qs.split("&")) {
        String[] kv = kvPair.split("=", 2);
        if (kv[0].length() == 0) {
          continue;
        }

        List<String> values = out.get(kv[0]);
        if (values == null) {
          values = new ArrayList<String>();
          out.put(kv[0], values);
        }
        values.add(kv.length > 1 ? URL.decodeQueryString(kv[1]) : "");
      }
    }

    for (Map.Entry<String, List<String>> entry : out.entrySet()) {
      entry.setValue(Collections.unmodifiableList(entry.getValue()));
    }

    out = Collections.unmodifiableMap(out);

    return out;
  }

  /**
   * Forces the child UI to be rendered in the container.
   */
  public abstract void go(final HasWidgets container);

  /**
   * Used to bind widgets with their handlers.
   */
  public abstract void bind();
}
